#!/usr/bin/env node

const fs = require('fs');
const path = require('path');
const { exec, spawn } = require('child_process');
const chalk = require('chalk');
const ora = require('ora');

class ImprovedDevServer {
  constructor() {
    this.sourceDir = path.join(__dirname, '..', 'src');
    this.distDir = path.join(__dirname, '..', 'dist');
    this.watchers = new Map();
    this.isBuilding = false;
    this.httpServer = null;
    this.port = 8080;
    this.debounceTimer = null;
    this.buildCount = 0;
  }

  async start() {
    console.log(chalk.cyan('🚀 启动改进的开发服务器...'));
    
    // 首次构建
    await this.build();
    
    // 启动HTTP服务器
    this.startHttpServer();
    
    // 启动文件监听
    this.startWatching();
    
    console.log(chalk.green(`✅ 开发服务器已启动: http://localhost:${this.port}`));
    console.log(chalk.yellow('💡 提示: 修改源文件后会自动重新构建'));
    console.log(chalk.gray('按 Ctrl+C 停止服务器'));
  }

  async build() {
    if (this.isBuilding) {
      console.log(chalk.yellow('⏳ 构建中，跳过此次请求...'));
      return;
    }

    this.isBuilding = true;
    this.buildCount++;
    const spinner = ora(`🔄 构建项目 (第${this.buildCount}次)...`).start();

    return new Promise((resolve, reject) => {
      const buildScript = path.join(__dirname, 'build.js');
      exec(`node "${buildScript}"`, (error, stdout, stderr) => {
        this.isBuilding = false;
        
        if (error) {
          spinner.fail(chalk.red('❌ 构建失败'));
          console.error(chalk.red('错误信息:'), error.message);
          if (stderr) {
            console.error(chalk.red('错误详情:'), stderr);
          }
          reject(error);
          return;
        }
        
        if (stderr) {
          console.warn(chalk.yellow('⚠️  构建警告:'), stderr);
        }
        
        spinner.succeed(chalk.green(`✅ 构建完成 (第${this.buildCount}次)`));
        
        // 显示构建后的文件信息
        this.showBuildInfo();
        
        resolve();
      });
    });
  }

  showBuildInfo() {
    try {
      // 检查demos目录
      const demosDir = path.join(this.distDir, 'demos');
      if (fs.existsSync(demosDir)) {
        const demos = fs.readdirSync(demosDir, { withFileTypes: true })
          .filter(dirent => dirent.isDirectory())
          .map(dirent => dirent.name);
        console.log(chalk.blue(`📁 构建了 ${demos.length} 个案例到 dist/demos/`));
      }

      // 检查最新的案例文件
      const latestDemos = this.getLatestModifiedDemos();
      if (latestDemos.length > 0) {
        console.log(chalk.cyan('📝 最新修改的案例:'));
        latestDemos.forEach(demo => {
          console.log(chalk.gray(`   - ${demo.name} (${demo.folder})`));
        });
      }
    } catch (error) {
      console.warn(chalk.yellow('⚠️  无法获取构建信息:'), error.message);
    }
  }

  getLatestModifiedDemos() {
    try {
      const demosDir = path.join(this.distDir, 'demos');
      if (!fs.existsSync(demosDir)) return [];

      const demos = fs.readdirSync(demosDir, { withFileTypes: true })
        .filter(dirent => dirent.isDirectory())
        .map(dirent => {
          const demoPath = path.join(demosDir, dirent.name);
          const htmlPath = path.join(demoPath, 'index.html');
          const stats = fs.existsSync(htmlPath) ? fs.statSync(htmlPath) : null;
          return {
            name: dirent.name,
            folder: dirent.name,
            mtime: stats ? stats.mtime : new Date(0)
          };
        })
        .sort((a, b) => b.mtime - a.mtime)
        .slice(0, 3);

      return demos;
    } catch (error) {
      return [];
    }
  }

  startHttpServer() {
    if (this.httpServer) {
      this.httpServer.kill();
    }

    // 使用更详细的HTTP服务器配置
    this.httpServer = spawn('npx', [
      'http-server', 
      'dist', 
      '-p', this.port.toString(), 
      '--cors',
      '--cache', '-1', // 禁用缓存
      '--gzip',
      '--brotli'
    ], {
      stdio: 'inherit',
      shell: true
    });

    this.httpServer.on('error', (error) => {
      console.error(chalk.red('HTTP服务器启动失败:'), error);
    });

    this.httpServer.on('exit', (code) => {
      if (code !== 0) {
        console.error(chalk.red(`HTTP服务器异常退出，代码: ${code}`));
      }
    });
  }

  startWatching() {
    console.log(chalk.cyan('🔍 启动文件监听...'));
    console.log(chalk.gray(`监听目录: ${this.sourceDir}`));
    
    // 监听src目录
    this.watchDirectory(this.sourceDir);
    
    // 也监听根目录的index.html
    const rootIndexPath = path.join(__dirname, '..', 'index.html');
    if (fs.existsSync(rootIndexPath)) {
      this.watchFile(rootIndexPath);
    }
  }

  watchDirectory(dir) {
    if (!fs.existsSync(dir)) {
      console.warn(chalk.yellow(`⚠️  目录不存在: ${dir}`));
      return;
    }

    if (!dir.startsWith(this.sourceDir) && !dir.includes('index.html')) {
      return;
    }

    const watcher = fs.watch(dir, { recursive: true }, (eventType, filename) => {
      if (filename && this.shouldWatchFile(filename)) {
        this.handleFileChange(eventType, filename, dir);
      }
    });

    this.watchers.set(dir, watcher);

    // 递归监听子目录
    try {
      const items = fs.readdirSync(dir);
      for (const item of items) {
        const itemPath = path.join(dir, item);
        const stat = fs.statSync(itemPath);
        if (stat.isDirectory() && !this.shouldIgnoreDirectory(item)) {
          this.watchDirectory(itemPath);
        }
      }
    } catch (error) {
      console.warn(chalk.yellow(`⚠️  无法读取目录: ${dir}`));
    }
  }

  watchFile(filePath) {
    if (!fs.existsSync(filePath)) return;

    const watcher = fs.watch(filePath, (eventType, filename) => {
      if (filename) {
        this.handleFileChange(eventType, filename, path.dirname(filePath));
      }
    });

    this.watchers.set(filePath, watcher);
  }

  shouldWatchFile(filename) {
    const ext = path.extname(filename).toLowerCase();
    const watchExtensions = ['.html', '.css', '.js', '.json', '.svg', '.png', '.jpg', '.jpeg', '.gif', '.webp'];
    return watchExtensions.includes(ext);
  }

  shouldIgnoreDirectory(dirname) {
    const ignoreDirs = ['node_modules', '.git', 'dist', 'build', '.vscode', '.idea', 'temp', 'tmp', 'templates'];
    return ignoreDirs.includes(dirname);
  }

  shouldIgnoreFile(filePath) {
    const tempPatterns = [
      /\.tmp$/,
      /\.temp$/,
      /~$/,
      /\.swp$/,
      /\.swo$/,
      /\.DS_Store$/,
      /Thumbs\.db$/
    ];
    
    for (const pattern of tempPatterns) {
      if (pattern.test(filePath)) {
        return true;
      }
    }
    
    if (filePath.includes('/dist/') || filePath.includes('\\dist\\')) {
      return true;
    }
    
    return false;
  }

  handleFileChange(eventType, filename, dir) {
    if (!dir.startsWith(this.sourceDir) && !dir.includes('index.html')) {
      return;
    }

    const filePath = path.join(dir, filename);
    const relativePath = path.relative(process.cwd(), filePath);
    
    if (this.shouldIgnoreFile(filePath)) {
      return;
    }
    
    console.log(chalk.blue(`📝 文件变化: ${relativePath} (${eventType})`));
    
    // 立即显示变化，然后防抖构建
    this.debounceBuild();
  }

  debounceBuild() {
    if (this.isBuilding) {
      return;
    }

    if (this.debounceTimer) {
      clearTimeout(this.debounceTimer);
    }

    this.debounceTimer = setTimeout(async () => {
      if (this.isBuilding) {
        return;
      }

      try {
        await this.build();
        console.log(chalk.green('🔄 页面已更新！请刷新浏览器查看变化'));
        console.log(chalk.yellow('💡 如果页面没有更新，请尝试强制刷新 (Ctrl+F5 或 Cmd+Shift+R)'));
      } catch (error) {
        console.error(chalk.red('构建失败，请检查错误信息'));
      }
    }, 300); // 减少防抖时间到300ms
  }

  stop() {
    console.log(chalk.yellow('\n🛑 停止开发服务器...'));
    
    for (const [dir, watcher] of this.watchers) {
      watcher.close();
    }
    this.watchers.clear();
    
    if (this.httpServer) {
      this.httpServer.kill();
    }
    
    if (this.debounceTimer) {
      clearTimeout(this.debounceTimer);
    }
    
    console.log(chalk.green('✅ 开发服务器已停止'));
    process.exit(0);
  }
}

// 启动开发服务器
const devServer = new ImprovedDevServer();

// 处理进程退出
process.on('SIGINT', () => {
  devServer.stop();
});

process.on('SIGTERM', () => {
  devServer.stop();
});

// 启动服务器
devServer.start().catch(error => {
  console.error(chalk.red('❌ 启动开发服务器失败:'), error);
  process.exit(1);
});
